#include "main.h"


/**
*  Instantiates the \c MatrixTest class.
*  \version 1.0.0a
*  \date    3 August 2010
*/
MatrixTest::MatrixTest()
{
}


/**
*  Instantiates a \c Matrix class with the constructor \c Matrix() and checks that the number of dimensions is correct and that
*  each dimension has length 0.
*  \version 1.1.3a
*  \date    31 January 2011
*/
void MatrixTest::testEmptyMatrix()
{
    // Test matrix with dimensions = 0
    TRY
        Matrix<double,unsigned int,0> A;
        QVERIFY2(A.getDimensions() == 0, "Matrix class constructor error: matrix must have 0 dimensions.");
    FAIL_ON_EXCEPTION

    // Test empty matrix with maximum number of dimensions
    TRY
        Matrix<double,unsigned long long,63> A;
        QVERIFY2(A.getDimensions() == 63, "Matrix class constructor error: matrix must have 63 dimensions.");
        unsigned char i;

        for( i = 0; i < 63; i++ )
        {
            QVERIFY2(A.getSize(i) == 0, "Matrix class constructor error: each matrix dimension must have size 0.");
        }
    FAIL_ON_EXCEPTION

    // Test empty matrix that exceeds the maximum number of dimensions allowed
    TRY
        Matrix<double,unsigned int,64> A;
    EXPECT_EXCEPTION( "Matrix class constructor error: dimensions overflow not recognized." )

    // Test square matrix flag is set properly
    TRY
        Matrix<double,unsigned int,2> A;
        QVERIFY2( !A.isSquare(), "Matrix class constructor error: matrix flag not set properly.");
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates a N-dimensional \c Matrix class with the constructor <tt> Matrix(const LengthType (&size)[dimensions]) </tt> and
*  checks:
*  - the number of dimensions;
*  - the size of each dimension;
*  - that every data element is set to 0.\n \n
*  \version 1.0.4a
*  \date    31 January 2011
*/
void MatrixTest::testMatrix()
{
    // Test any matrix
    TRY
        Matrix(A,double,unsigned int,3) {21,65,10} End;
        QVERIFY2(A.getDimensions() == 3, "Matrix class constructor error: matrix must have 3 dimensions.");
        QVERIFY2(A.getSize(0) == 21, "Matrix class constructor error: the size of the 1st dimension must be 21.");
        QVERIFY2(A.getSize(1) == 65, "Matrix class constructor error: the size of the 2nd dimension must be 65.");
        QVERIFY2(A.getSize(2) == 10, "Matrix class constructor error: the size of the 3rd dimension must be 10.");
        unsigned int i;

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2(A(i) == 0, "Matrix class constructor error: the value of each data element must be 0.");
        }
    FAIL_ON_EXCEPTION

    TRY
        Matrix(A,double,unsigned int,64) {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
                                          2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2} End;
    EXPECT_EXCEPTION( "Matrix class constructor error: dimension overflow not recognized." )

    // Test maximum length overflow
    TRY
        Matrix(A,double,unsigned char,2) {255,2} End;
    EXPECT_EXCEPTION( "Matrix class constructor error: length overflow not recognized." )

    // Test data memory overflow
    TRY
        Matrix(A,double,unsigned long long,2) {0xFFFFFFFF,1} End;
    LOOKFOR_EXCEPTION( "Matrix class constructor warning: memory overflow has not happened." )

    // Test square matrix flag is set properly
    TRY
        Matrix(A,double,unsigned int,2) {4,4} End;
        QVERIFY2( A.isSquare(), "Matrix class constructor error: matrix flag not set properly.");
    FAIL_ON_EXCEPTION

    TRY
        Matrix(A,double,unsigned int,2) {4,3} End;
        QVERIFY2( !A.isSquare(), "Matrix class constructor error: matrix flag not set properly.");
    FAIL_ON_EXCEPTION

    TRY
        Matrix(A,double,unsigned int,3) {4,4,4} End;
        QVERIFY2( !A.isSquare(), "Matrix class constructor error: matrix flag not set properly.");
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates a \c Matrix class with the constructor <tt> Matrix(const Matrix& m) </tt> and checks the equality of the following
*  elements:
*  - dimensions;
*  - size of each dimension;
*  - every data element.\n \n
*  \version 1.0.0a
*  \date    3 September 2010
*/
void MatrixTest::testCopyMatrix()
{
    TRY
        Matrix(A,double,unsigned int,3) {21,65,10} End;
        Matrix<double,unsigned int,3> B(A);
        QVERIFY2(B.getDimensions() == 3, "Matrix class constructor error: matrix must have 3 dimensions.");
        QVERIFY2(B.getSize(0) == 21, "Matrix class constructor error: the size of the 1st dimension must be 21.");
        QVERIFY2(B.getSize(1) == 65, "Matrix class constructor error: the size of the 2nd dimension must be 65.");
        QVERIFY2(B.getSize(2) == 10, "Matrix class constructor error: the size of the 3rd dimension must be 10.");
        unsigned int i;

        for( i = 0; i < B.getLength(); i++ )
        {
            QVERIFY2(B(i) == 0, "Matrix class constructor error: the value of each data element must be 0.");
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates a \c Matrix class and checks that the retrieved dimensions are equal to the value used for instantiation.
*  \version 1.0.0a
*  \date    3 September 2010
*/
void MatrixTest::testGetDimensions()
{
    TRY
        Matrix<double,unsigned int,12> A;
        QVERIFY2(A.getDimensions() == 12, "Dimensions accessor error: returned value must be 12.");
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates a \c Matrix class and checks that the retrieved length is equal to the product of each dimension size.
*  \version 1.0.0a
*  \date    3 September 2010
*/
void MatrixTest::testGetLength()
{
    TRY
        Matrix(A,double,unsigned int,3) {21,65,10} End;
        QVERIFY2(A.getLength() == 21 * 65 * 10, "Length accessor error: returned value must be 13650.");
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates a \c Matrix class and checks that the retrieved size is equal to the one set in instantiation.
*  \version 1.0.1a
*  \date    6 September 2010
*/
void MatrixTest::testGetSize()
{
    // Test with zero dimensions matrix
    TRY
        Matrix<double,unsigned int,0> A;
        A.getSize(0);
    EXPECT_EXCEPTION( "Matrix class accessor error: no size available not recognized." )

    // Test with any matrix
    TRY
        Matrix(A,double,unsigned int,3) {21,65,10} End;
        QVERIFY2(A.getSize(0) == 21, "Size accessor error: the size of the 1st dimension must be 21.");
        QVERIFY2(A.getSize(1) == 65, "Size accessor error: the size of the 2nd dimension must be 65.");
        QVERIFY2(A.getSize(2) == 10, "Size accessor error: the size of the 3rd dimension must be 10.");
#ifdef DEBUG
        A.getSize(3);
    EXPECT_EXCEPTION( "Matrix class accessor error: index overflow not recognized." )
#else
    FAIL_ON_EXCEPTION
#endif
}


/**
*  Instantiates a \c Matrix class and checks the ability to set a data value and get the same value (through a single index).
*  \version 1.0.1a
*  \date    6 September 2010
*/
void MatrixTest::testDataAccessBySingleIndex()
{
#ifdef DEBUG
    // Test access to empty matrix
    TRY
        Matrix<double,unsigned char,2> A;
        A(3) = M_PI;
    EXPECT_EXCEPTION( "Data access error: access to empty matrix not recognized." )

    // Test index overflow
    TRY
        Matrix(A,double,unsigned char,2) {3,3} End;
        A(9) = M_PI;
    EXPECT_EXCEPTION( "Data access error: index overflow not recognized." )
#endif

    // Test access to any matrix
    TRY
        Matrix(A,double,unsigned char,2) {3,3} End;
        A(3) = M_PI;
        QVERIFY2(A(3) == M_PI, "Data access error: the retrieved value differs from the one set.");
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates a 2D \c Matrix class and checks:
*  - the ability to set a data value and get the same value (through row and column indices);
*  - that the data elements are disposed as a sequence of matrix rows.
*  \version 1.0.1a
*  \date    6 September 2010
*/
void MatrixTest::testDataAccessByTwoIndices()
{
#ifdef DEBUG
    // Test access to empty matrix
    TRY
        Matrix<double,unsigned char,2> A;
        A(1,2) = M_PI;
    EXPECT_EXCEPTION( "Data access error: access to empty matrix not recognized." )

    // Test index overflow
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        A(0,5) = M_PI;
    EXPECT_EXCEPTION( "Data access error: index overflow not recognized." )

    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        A(3,0) = M_PI;
    EXPECT_EXCEPTION( "Data access error: index overflow not recognized." )
#endif

    // Test SET and GET value
    TRY
        Matrix(A,double,unsigned char,2) {3,3} End;
        A(1,2) = M_PI;
        QVERIFY2(A(1,2) == M_PI, "Data access error: the retrieved value differs from the one set.");
    FAIL_ON_EXCEPTION

    // Test data disposition
    TRY
        Matrix(A,double,unsigned char,2) {3,3} End;
        A(1,2) = M_PI;
        QVERIFY2(A(5) == M_PI, "Data access error: the retrieved value differs from the one set.");
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks that assigment operation makes an exact copy of the right hand matrix into the left
*  hand one.
*  \version 1.0.0a
*  \date    6 September 2010
*/
void MatrixTest::testAssignmentMatrix()
{
    // Test assigment of a 0 dimensions matrix to a 0 dimensions matrix
    TRY
        Matrix<double,unsigned char,0> A, B;
        B = A;
        QVERIFY2(B.getLength() == 0, "Assignment error: the length of left hand matrix must be 0.");
    FAIL_ON_EXCEPTION

    // Test assigment of an empty matrix to an empty matrix
    TRY
        Matrix<double,unsigned char,2> A, B;
        B = A;
        QVERIFY2(B.getLength() == 0, "Assignment error: the length of left hand matrix must be 0.");
        unsigned char i;

        for( i = 0; i < 2; i++ )
        {
            QVERIFY2(B.getSize(i) == 0, "Assignment error: the size of each matrix dimension must be 0.");
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test assigment of an empty matrix to any matrix
    TRY
        Matrix<double,unsigned char,2> A;
        Matrix(B,double,unsigned char,2) {3,5} End;
        B = A;
    EXPECT_EXCEPTION( "Assignment error: matrices size mismatch not recognized." )

    // Test assigment of any matrix to an empty matrix
    TRY
        Matrix<double,unsigned char,2> A;
        Matrix(B,double,unsigned char,2) {3,5} End;
        A = B;
    EXPECT_EXCEPTION( "Assignment error: matrices size mismatch not recognized." )
#endif

    // Test assigment of any matrix to an equal size matrix
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < B.getLength(); i++ )
        {
            B(i) = M_PI * ( i + 1 );
        }

        A = B;
        QVERIFY2(A.getLength() == B.getLength(), "Assignment error: the lengths of the two matrices must be the same.");

        for( i = 0; i < 2; i++ )
        {
            QVERIFY2(A.getSize(i) == B.getSize(i), "Assignment error: the sizes of the two matrices must be the same.");
        }

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2(A(i) == B(i), "Assignment error: each data value of the two matrices must be equal.");
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates a \c Matrix class and a DataType value and checks that assigment operation writes the right hand value into each
*  data element of the left hand matrix.
*  \version 1.0.0a
*  \date    6 September 2010
*/
void MatrixTest::testAssignmentDataType()
{
    // Test assigment of a double to a 0 dimensions matrix
    TRY
        Matrix<double,unsigned char,0> A;
        double b;
        A = b;
        QVERIFY2(A.getLength() == 0, "Assignment error: the length of left hand matrix must be 0.");
    FAIL_ON_EXCEPTION

    // Test assigment of a double to any matrix
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        double b = M_PI;
        A = b;
        QVERIFY2(A.getLength() == 15, "Assignment error: the length of left hand matrix must not change.");
        QVERIFY2(A.getSize(0) == 3, "Assignment error: the size of each matrix dimension must not change.");
        QVERIFY2(A.getSize(1) == 5, "Assignment error: the size of each matrix dimension must not change.");
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2(A(i) == b, "Assignment error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks that addition operation adds each right hand matrix data value into each
*  data element of the left hand matrix.
*  \version 1.0.2a
*  \date    15 September 2010
*/
void MatrixTest::testAdditionMatrix()
{
    // Test addition of a matrix of the same size
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = M_E;
            B(i) = M_PI * ( i + 1 );
        }

        A += B;
        QVERIFY2(A.getLength() == B.getLength(), "Addition error: the length of left hand matrix must not change.");
        QVERIFY2(A.getSize(0) == B.getSize(0), "Addition error: the size of each matrix dimension must not change.");
        QVERIFY2(A.getSize(1) == B.getSize(1), "Addition error: the size of each matrix dimension must not change.");

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2( fabs( A(i) - ( M_E + M_PI * ( i + 1 ) ) ) < 1e-14, "Addition error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A += B;
    EXPECT_EXCEPTION( "Addition error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A += B;
    EXPECT_EXCEPTION( "Addition error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a DataType value and checks that addition operation adds right hand value into each
*  data element of the left hand matrix.
*  \version 1.0.1a
*  \date    15 September 2010
*/
void MatrixTest::testAdditionDataType()
{
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        double B = M_PI;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = M_E;
        }

        A += B;
        QVERIFY2(A.getLength() == 15, "Addition error: the length of left hand matrix must not change.");
        QVERIFY2(A.getSize(0) == 3, "Addition error: the size of each matrix dimension must not change.");
        QVERIFY2(A.getSize(1) == 5, "Addition error: the size of each matrix dimension must not change.");

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2( fabs( A(i) - ( M_E + M_PI ) ) < 1e-14, "Addition error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks that sum operation returns a \c Matrix that is the sum of \c this \c Matrix and
*  right hand matrix.
*  \version 1.0.1a
*  \date    15 September 2010
*/
void MatrixTest::testSumMatrix()
{
    // Test sum with a matrix of the same size
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {3,5} End;
        Matrix(C,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = M_E;
            B(i) = M_PI * ( i + 1 );
        }

        C = A + B;
        QVERIFY2(C.getLength() == B.getLength(), "Sum error: the length of left hand matrix must not change.");
        QVERIFY2(C.getSize(0) == B.getSize(0), "Sum error: the size of each matrix dimension must not change.");
        QVERIFY2(C.getSize(1) == B.getSize(1), "Sum error: the size of each matrix dimension must not change.");

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( fabs( C(i) - ( M_E + M_PI * ( i + 1 ) ) ) < 1e-14, "Sum error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A + B;
    EXPECT_EXCEPTION( "Sum error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A + B;
    EXPECT_EXCEPTION( "Sum error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a DataType value and checks that sum operation returns a \c Matrix that is the sum of \c this
*  \c Matrix and the left hand DataType value.
*  \version 1.0.1a
*  \date    15 September 2010
*/
void MatrixTest::testSumDataType()
{
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        double B = M_PI;
        Matrix(C,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = M_E;
        }

        C = A + B;
        QVERIFY2(C.getLength() == 15, "Sum error: the length of left hand matrix must not change.");
        QVERIFY2(C.getSize(0) == 3, "Sum error: the size of each matrix dimension must not change.");
        QVERIFY2(C.getSize(1) == 5, "Sum error: the size of each matrix dimension must not change.");

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( fabs( C(i) - ( M_E + M_PI ) ) < 1e-14, "Sum error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks that subtraction operation subtracts each right hand matrix data value from each
*  data element of the left hand matrix.
*  \version 1.0.0a
*  \date    15 September 2010
*/
void MatrixTest::testSubtractionMatrix()
{
    // Test subtraction of a matrix of the same size
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = M_E;
            B(i) = M_PI * ( i + 1 );
        }

        A -= B;
        QVERIFY2(A.getLength() == B.getLength(), "Subtraction error: the length of left hand matrix must not change.");
        QVERIFY2(A.getSize(0) == B.getSize(0), "Subtraction error: the size of each matrix dimension must not change.");
        QVERIFY2(A.getSize(1) == B.getSize(1), "Subtraction error: the size of each matrix dimension must not change.");

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2( fabs( A(i) - ( M_E - M_PI * ( i + 1 ) ) ) < 1e-14, "Subtraction error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A -= B;
    EXPECT_EXCEPTION( "Subtraction error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A -= B;
    EXPECT_EXCEPTION( "Subtraction error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a DataType value and checks that subtraction operation subtracts right hand value into each
*  data element of the left hand matrix.
*  \version 1.0.0a
*  \date    15 September 2010
*/
void MatrixTest::testSubtractionDataType()
{
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        double B = M_PI;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = M_E;
        }

        A -= B;
        QVERIFY2(A.getLength() == 15, "Subtraction error: the length of left hand matrix must not change.");
        QVERIFY2(A.getSize(0) == 3, "Subtraction error: the size of each matrix dimension must not change.");
        QVERIFY2(A.getSize(1) == 5, "Subtraction error: the size of each matrix dimension must not change.");

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2( fabs( A(i) - ( M_E - M_PI ) ) < 1e-14, "Subtraction error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks that difference operation returns a \c Matrix that is the difference of \c this
*  \c Matrix and right hand matrix.
*  \version 1.0.0a
*  \date    15 September 2010
*/
void MatrixTest::testDifferenceMatrix()
{
    // Test difference with a matrix of the same size
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {3,5} End;
        Matrix(C,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = M_E;
            B(i) = M_PI * ( i + 1 );
        }

        C = A - B;
        QVERIFY2(C.getLength() == B.getLength(), "Difference error: the length of left hand matrix must not change.");
        QVERIFY2(C.getSize(0) == B.getSize(0), "Difference error: the size of each matrix dimension must not change.");
        QVERIFY2(C.getSize(1) == B.getSize(1), "Difference error: the size of each matrix dimension must not change.");

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( abs( C(i) - ( M_E - M_PI * ( i + 1 ) ) ) < 1e-14, "Difference error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A - B;
    EXPECT_EXCEPTION( "Difference error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A - B;
    EXPECT_EXCEPTION( "Difference error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a DataType value and checks that difference operation returns a \c Matrix that is the
*  difference of \c this \c Matrix and the left hand DataType value.
*  \version 1.0.0a
*  \date    15 September 2010
*/
void MatrixTest::testDifferenceDataType()
{
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        double B = M_PI;
        Matrix(C,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = M_E;
        }

        C = A - B;
        QVERIFY2(C.getLength() == 15, "Difference error: the length of left hand matrix must not change.");
        QVERIFY2(C.getSize(0) == 3, "Difference error: the size of each matrix dimension must not change.");
        QVERIFY2(C.getSize(1) == 5, "Difference error: the size of each matrix dimension must not change.");

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( fabs( C(i) - ( M_E - M_PI ) ) < 1e-14, "Difference error: each data value of the matrix must be equal to the assigned value.");
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two 2D \c Matrix classes and checks that multiplication operation returns a 2D \c Matrix that is the row by columns
*  product of \c this \c Matrix and right hand matrix.
*  \version 1.0.1a
*  \date    15 November 2010
*  \todo    Test for all exceptions is not possible, because the test causes compilation errors. To be solved, with low priority.
*/
void MatrixTest::testMultiplicationMatrix()
{
    // Test multiplication with a matrix with the same size of the second dimension
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
            B(i) = i + 1;
        }

        for( i = A.getLength(); i < B.getLength(); i++ )
        {
            B(i) = i + 1;
        }

        A *= B;
        QVERIFY2( A.getLength() == 15, "Multiplication error: the length of left hand matrix must not change." );
        QVERIFY2( A.getSize(0) == 3, "Multiplication error: the size of each matrix dimension must not change." );
        QVERIFY2( A.getSize(1) == 5, "Multiplication error: the size of each matrix dimension must not change." );
        QVERIFY2( A(0,0) == 215, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,1) == 230, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,2) == 245, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,3) == 260, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,4) == 275, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,0) == 490, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,1) == 530, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,2) == 570, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,3) == 610, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,4) == 650, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,0) == 765, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,1) == 830, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,2) == 895, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,3) == 960, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,4) == 1025, "Multiplication error: the calculation is not correct." );
    FAIL_ON_EXCEPTION

    // Test multiplication with a matrix with a greater size of the second dimension
    TRY
        Matrix(A,double,unsigned char,2) {3,4} End;
        Matrix(B,double,unsigned char,2) {4,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
            B(i) = i + 1;
        }

        for( i = A.getLength(); i < B.getLength(); i++ )
        {
            B(i) = i + 1;
        }

        A *= B;
        QVERIFY2( A.getLength() == 15, "Multiplication error: the length of left hand matrix must not change." );
        QVERIFY2( A.getSize(0) == 3, "Multiplication error: the size of each matrix dimension must not change." );
        QVERIFY2( A.getSize(1) == 5, "Multiplication error: the size of each matrix dimension must not change." );
        QVERIFY2( A(0,0) == 110, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,1) == 120, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,2) == 130, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,3) == 140, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,4) == 150, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,0) == 246, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,1) == 272, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,2) == 298, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,3) == 324, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,4) == 350, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,0) == 382, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,1) == 424, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,2) == 466, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,3) == 508, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,4) == 550, "Multiplication error: the calculation is not correct." );
    FAIL_ON_EXCEPTION

    // Test multiplication with a matrix with a smaller size of the second dimension
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,2} End;
        unsigned char i;

        for( i = 0; i < B.getLength(); i++ )
        {
            A(i) = i + 1;
            B(i) = i + 1;
        }

        for( i = B.getLength(); i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        A *= B;
        QVERIFY2( A.getLength() == 6, "Multiplication error: the length of left hand matrix must not change." );
        QVERIFY2( A.getSize(0) == 3, "Multiplication error: the size of each matrix dimension must not change." );
        QVERIFY2( A.getSize(1) == 2, "Multiplication error: the size of each matrix dimension must not change." );
        QVERIFY2( A(0,0) == 95, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(0,1) == 110, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,0) == 220, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(1,1) == 260, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,0) == 345, "Multiplication error: the calculation is not correct." );
        QVERIFY2( A(2,1) == 410, "Multiplication error: the calculation is not correct." );
    FAIL_ON_EXCEPTION

    // Test dimension mismatch
//    TRY
//        Matrix(A,double,unsigned char,1) {3} End;
//        Matrix(B,double,unsigned char,2) {1,2} End;
//        A *= B;
//    EXPECT_EXCEPTION( "Multiplication error: dimension mismatch not recognized." )

    // Test operation not supported
//    TRY
//        Matrix(A,double,unsigned char,3) {3,2,4} End;
//        Matrix(B,double,unsigned char,2) {2,2} End;
//        A *= B;
//    EXPECT_EXCEPTION( "Multiplication error: operation not supported not recognized." )

#ifdef DEBUG
    // Test inner dimensions mismatch
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,3} End;
        A *= B;
    EXPECT_EXCEPTION( "Multiplication error: inner dimensions mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a DataType value and checks that multiplication operation returns a \c Matrix that is
*  the product of \c this \c Matrix and right hand DataType value.
*  \version 1.0.0a
*  \date    24 January 2011
*/
void MatrixTest::testMultiplicationDataType()
{
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        double B = 1.5;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        A *= B;
        QVERIFY2( A.getLength() == 15, "Multiplication error: the length of left hand matrix must not change." );
        QVERIFY2( A.getSize(0) == 3, "Multiplication error: the size of each matrix dimension must not change." );
        QVERIFY2( A.getSize(1) == 5, "Multiplication error: the size of each matrix dimension must not change." );

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2( A(i) == ( i + 1 ) * B, "Multiplication error: the calculation is not correct." );
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two 2D \c Matrix classes and a 1D (left-hand) and a 2D (right-hand) matrices and checks that product operation
*  returns a 2D \c Matrix that is the row by columns product of \c this \c Matrix and right hand matrix.
*  \version 1.1.0a
*  \date    28 January 2011
*/
void MatrixTest::testProduct2DMatrix()
{
    // Test product 2D * 2D = 2D
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,4} End;
        Matrix(C,double,unsigned char,2) {3,4} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
            B(i) = i + 1;
        }

        for( i = A.getLength(); i < B.getLength(); i++ )
        {
            B(i) = i + 1;
        }

        C = A * B;
        QVERIFY2( C.getLength() == 12, "Product error: the length of the result is wrong." );
        QVERIFY2( C.getSize(0) == 3, "Product error: the number of rows of result is wrong." );
        QVERIFY2( C.getSize(1) == 4, "Product error: the number of columns of result is wrong." );
        QVERIFY2( C(0,0) == 175, "Product error: the calculation is not correct." );
        QVERIFY2( C(0,1) == 190, "Product error: the calculation is not correct." );
        QVERIFY2( C(0,2) == 205, "Product error: the calculation is not correct." );
        QVERIFY2( C(0,3) == 220, "Product error: the calculation is not correct." );
        QVERIFY2( C(1,0) == 400, "Product error: the calculation is not correct." );
        QVERIFY2( C(1,1) == 440, "Product error: the calculation is not correct." );
        QVERIFY2( C(1,2) == 480, "Product error: the calculation is not correct." );
        QVERIFY2( C(1,3) == 520, "Product error: the calculation is not correct." );
        QVERIFY2( C(2,0) == 625, "Product error: the calculation is not correct." );
        QVERIFY2( C(2,1) == 690, "Product error: the calculation is not correct." );
        QVERIFY2( C(2,2) == 755, "Product error: the calculation is not correct." );
        QVERIFY2( C(2,3) == 820, "Product error: the calculation is not correct." );
    FAIL_ON_EXCEPTION

    // Test product 1D * 2D = 2D
    TRY
        Matrix(A,double,unsigned char,1) {3} End;
        Matrix(B,double,unsigned char,2) {1,4} End;
        Matrix(C,double,unsigned char,2) {3,4} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
            B(i) = i + 1;
        }

        for( i = A.getLength(); i < B.getLength(); i++ )
        {
            B(i) = i + 1;
        }

        C = A * B;
        QVERIFY2( C.getLength() == 12, "Product error: the length of the result is wrong." );
        QVERIFY2( C.getSize(0) == 3, "Product error: the number of rows of result is wrong." );
        QVERIFY2( C.getSize(1) == 4, "Product error: the number of columns of result is wrong." );
        QVERIFY2( C(0,0) == 1, "Product error: the calculation is not correct." );
        QVERIFY2( C(0,1) == 2, "Product error: the calculation is not correct." );
        QVERIFY2( C(0,2) == 3, "Product error: the calculation is not correct." );
        QVERIFY2( C(0,3) == 4, "Product error: the calculation is not correct." );
        QVERIFY2( C(1,0) == 2, "Product error: the calculation is not correct." );
        QVERIFY2( C(1,1) == 4, "Product error: the calculation is not correct." );
        QVERIFY2( C(1,2) == 6, "Product error: the calculation is not correct." );
        QVERIFY2( C(1,3) == 8, "Product error: the calculation is not correct." );
        QVERIFY2( C(2,0) == 3, "Product error: the calculation is not correct." );
        QVERIFY2( C(2,1) == 6, "Product error: the calculation is not correct." );
        QVERIFY2( C(2,2) == 9, "Product error: the calculation is not correct." );
        QVERIFY2( C(2,3) == 12, "Product error: the calculation is not correct." );
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test inner dimensions mismatch (2D)
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,3} End;
        A * B;
    EXPECT_EXCEPTION( "Product error: inner dimensions mismatch not recognized." )

    // Test inner dimensions mismatch (1D)
    TRY
        Matrix(A,double,unsigned char,1) {3} End;
        Matrix(B,double,unsigned char,2) {4,3} End;
        A * B;
    EXPECT_EXCEPTION( "Product error: inner dimensions mismatch not recognized." )
#endif
}


/**
*  Instantiates a 2D (left-hand) and a 1D (right-hand) matrices and two 1D matrices and checks that product operation returns a 1D
*  \c Matrix that is the row by columns product of \c this \c Matrix and right hand matrix.
*  \version 1.0.0a
*  \date    28 January 2011
*/
void MatrixTest::testProduct1DMatrix()
{
    // Test product 2D * 1D = 1D
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,1) {5} End;
        Matrix(C,double,unsigned char,1) {3} End;
        unsigned char i;

        for( i = 0; i < B.getLength(); i++ )
        {
            A(i) = i + 1;
            B(i) = i + 1;
        }

        for( i = B.getLength(); i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        C = A * B;

        QVERIFY2( C.getLength() == 3, "Product error: the length of the result is wrong." );
        QVERIFY2( C.getSize(0) == 3, "Product error: the number of rows of result is wrong." );
        QVERIFY2( C(0) == 55, "Product error: the calculation is not correct." );
        QVERIFY2( C(1) == 130, "Product error: the calculation is not correct." );
        QVERIFY2( C(2) == 205, "Product error: the calculation is not correct." );
    FAIL_ON_EXCEPTION

    // Test product 1D * 1D = 1D
    TRY
        Matrix(A,double,unsigned char,1) {3} End;
        Matrix(B,double,unsigned char,1) {1} End;
        Matrix(C,double,unsigned char,1) {3} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        B(0) = 2.5;
        C = A * B;
        QVERIFY2( C.getLength() == 3, "Product error: the length of the result is wrong." );
        QVERIFY2( C.getSize(0) == 3, "Product error: the number of rows of result is wrong." );
        QVERIFY2( C(0) == 2.5, "Product error: the calculation is not correct." );
        QVERIFY2( C(1) == 5, "Product error: the calculation is not correct." );
        QVERIFY2( C(2) == 7.5, "Product error: the calculation is not correct." );
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test inner dimensions mismatch (2D)
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,1) {4} End;
        A * B;
    EXPECT_EXCEPTION( "Product error: inner dimensions mismatch not recognized." )

    // Test inner dimensions mismatch (1D)
    TRY
        Matrix(A,double,unsigned char,1) {3} End;
        Matrix(B,double,unsigned char,1) {4} End;
        A * B;
    EXPECT_EXCEPTION( "Product error: inner dimensions mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a DataType value and checks that product operation returns a \c Matrix that is
*  the product of \c this \c Matrix and right hand DataType value.
*  \version 1.0.0a
*  \date    28 January 2011
*/
void MatrixTest::testProductDataType()
{
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        double B = 1.5;
        Matrix(C,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        C = A * B;
        QVERIFY2( C.getLength() == 15, "Product error: the length of the result is wrong." );
        QVERIFY2( C.getSize(0) == 3, "Product error: the number of rows of result is wrong." );
        QVERIFY2( C.getSize(1) == 5, "Product error: the number of columns of result is wrong." );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( C(i) == ( i + 1 ) * B, "Product error: the calculation is not correct." );
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks them for equality.
*  \version 1.2.0a
*  \date    7 February 2011
*/
void MatrixTest::testEqualityMatrix()
{
    // Test equality of identical matrices and then with an element changed
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix<double,unsigned char,2> B( A );
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A == B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( C(i), "Comparison error: equality not recognized." );
        }

        B(14) = 0;
        C = ( A == B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( !C(i), "Comparison error: equality recognized." );
            }
            else
            {
                QVERIFY2( C(i), "Comparison error: equality not recognized." );
            }
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A == B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A == B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a scalar value and checks them for equality.
*  \version 1.0.0a
*  \date    8 February 2011
*/
void MatrixTest::testEqualityDataType()
{
    // Test equality
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = 1;
        }

        double B = A(0);
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A == B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( C(i), "Comparison error: equality not recognized." );
        }

        A(14) = 0;
        C = ( A == B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( !C(i), "Comparison error: equality recognized." );
            }
            else
            {
                QVERIFY2( C(i), "Comparison error: equality not recognized." );
            }
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks them for inequality.
*  \version 1.2.0a
*  \date    7 February 2011
*/
void MatrixTest::testInequalityMatrix()
{
    // Test inequality of identical matrices and then with an element changed
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix<double,unsigned char,2> B( A );
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A != B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( !C(i), "Comparison error: inequality recognized." );
        }

        B(14) = 0;
        C = ( A != B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( C(i), "Comparison error: inequality not recognized." );
            }
            else
            {
                QVERIFY2( !C(i), "Comparison error: inequality recognized." );
            }
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A != B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A != B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a scalar value and checks them for inequality.
*  \version 1.0.0a
*  \date    8 February 2011
*/
void MatrixTest::testInequalityDataType()
{
    // Test inequality
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = 1;
        }

        double B = A(0);
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A != B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( !C(i), "Comparison error: inequality recognized." );
        }

        A(14) = 0;
        C = ( A != B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( C(i), "Comparison error: inequality not recognized." );
            }
            else
            {
                QVERIFY2( !C(i), "Comparison error: inequality recognized." );
            }
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks them for greater than comparison.
*  \version 1.0.1a
*  \date    8 February 2011
*/
void MatrixTest::testGreaterThanMatrix()
{
    // Test greater than comparison of identical matrices and then with an element changed
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix<double,unsigned char,2> B( A );
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A > B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( !C(i), "Comparison error: greater than comparison recognized." );
        }

        B(14) -= 1;
        C = ( A > B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( C(i), "Comparison error: greater than comparison not recognized." );
            }
            else
            {
                QVERIFY2( !C(i), "Comparison error: greater than comparison recognized." );
            }
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A > B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A > B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a scalar value and performs greater than comparison.
*  \version 1.0.0a
*  \date    8 February 2011
*/
void MatrixTest::testGreaterThanDataType()
{
    // Test greater than comparison
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = 1;
        }

        double B = A(0);
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A > B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( !C(i), "Comparison error: greater than comparison recognized." );
        }

        A(14) += 1;
        C = ( A > B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( C(i), "Comparison error: greater than comparison not recognized." );
            }
            else
            {
                QVERIFY2( !C(i), "Comparison error: greater than comparison recognized." );
            }
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks them for greater than or equal to comparison.
*  \version 1.0.1a
*  \date    8 February 2011
*/
void MatrixTest::testGreaterThanEqualToMatrix()
{
    // Test greater than or equal to comparison of identical matrices and then with an element changed
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix<double,unsigned char,2> B( A );
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A >= B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( C(i), "Comparison error: greater than or equal to comparison recognized." );
        }

        B(14) += 1;
        C = ( A >= B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( !C(i), "Comparison error: greater than or equal to comparison recognized." );
            }
            else
            {
                QVERIFY2( C(i), "Comparison error: greater than or equal to comparison not recognized." );
            }
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A >= B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A >= B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a scalar value and performs greater than or equal to comparison.
*  \version 1.0.0a
*  \date    8 February 2011
*/
void MatrixTest::testGreaterThanEqualToDataType()
{
    // Test greater than or equal to comparison
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = 1;
        }

        double B = A(0);
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A >= B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( C(i), "Comparison error: greater than or equal to comparison recognized." );
        }

        A(14) -= 1;
        C = ( A >= B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( !C(i), "Comparison error: greater than or equal to comparison recognized." );
            }
            else
            {
                QVERIFY2( C(i), "Comparison error: greater than or equal to comparison not recognized." );
            }
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks them for lower than comparison.
*  \version 1.0.0a
*  \date    7 February 2011
*/
void MatrixTest::testLowerThanMatrix()
{
    // Test lower than comparison of identical matrices and then with an element changed
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix<double,unsigned char,2> B( A );
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A < B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( !C(i), "Comparison error: lower than comparison recognized." );
        }

        B(14) = B(14) + 1;
        C = ( A < B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( C(i), "Comparison error: lower than comparison not recognized." );
            }
            else
            {
                QVERIFY2( !C(i), "Comparison error: lower than comparison recognized." );
            }
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A < B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A < B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a scalar value and performs lower than comparison.
*  \version 1.0.0a
*  \date    8 February 2011
*/
void MatrixTest::testLowerThanDataType()
{
    // Test lower than comparison
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = 1;
        }

        double B = A(0);
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A < B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( !C(i), "Comparison error: lower than comparison recognized." );
        }

        A(14) -= 1;
        C = ( A < B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( C(i), "Comparison error: lower than comparison not recognized." );
            }
            else
            {
                QVERIFY2( !C(i), "Comparison error: lower than comparison recognized." );
            }
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks them for lower than or equal to comparison.
*  \version 1.0.0a
*  \date    7 February 2011
*/
void MatrixTest::testLowerThanEqualToMatrix()
{
    // Test lower than or equal to comparison of identical matrices and then with an element changed
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix<double,unsigned char,2> B( A );
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A <= B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( C(i), "Comparison error: lower than or equal to comparison recognized." );
        }

        B(14) = B(14) - 1;
        C = ( A <= B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( !C(i), "Comparison error: lower than or equal to comparison recognized." );
            }
            else
            {
                QVERIFY2( C(i), "Comparison error: lower than or equal to comparison not recognized." );
            }
        }
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test size mismatch with same lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;
        A <= B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )

    // Test size mismatch with different lengths
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {4,2} End;
        A <= B;
    EXPECT_EXCEPTION( "Comparison error: matrices size mismatch not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and a scalar value and performs lower than or equal to comparison.
*  \version 1.0.0a
*  \date    8 February 2011
*/
void MatrixTest::testLowerThanEqualToDataType()
{
    // Test lower than or equal to comparison
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = 1;
        }

        double B = A(0);
        Matrix(C,bool,unsigned char,2) {3,5} End;
        C = ( A <= B );

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( C(i), "Comparison error: lower than or equal to comparison recognized." );
        }

        A(14) += 1;
        C = ( A <= B );

        for( i = 0; i < C.getLength(); i++ )
        {
            if( i == 14 )
            {
                QVERIFY2( !C(i), "Comparison error: lower than or equal to comparison recognized." );
            }
            else
            {
                QVERIFY2( C(i), "Comparison error: lower than or equal to comparison not recognized." );
            }
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks that copy operation makes an exact copy of \c this matrix into the specified one.
*  \version 1.0.2a
*  \date    31 January 2011
*/
void MatrixTest::testCopy()
{
    // Test copy of a 0 dimensions matrix to a 0 dimensions matrix
    TRY
        Matrix<double,unsigned char,0> A, B;
        A.copy( B );
        QVERIFY2(A.getLength() == 0, "Copy error: the length of left hand matrix must be 0.");
    FAIL_ON_EXCEPTION

    // Test copy of an empty matrix to an empty matrix
    TRY
        Matrix<double,unsigned char,2> A, B;
        A.copy( B );
        QVERIFY2(A.getLength() == 0, "Copy error: the length of left hand matrix must be 0.");
        unsigned char i;

        for( i = 0; i < 2; i++ )
        {
            QVERIFY2(A.getSize(i) == 0, "Copy error: the size of each matrix dimension must be 0.");
        }
    FAIL_ON_EXCEPTION

    // Test copy of an empty matrix to any matrix
    TRY
        Matrix<double,unsigned char,2> A;
        Matrix(B,double,unsigned char,2) {3,3} End;
        B.copy( A );
        QVERIFY2(B.getLength() == 0, "Copy error: the length of left hand matrix must be 0.");
        QVERIFY2(!B.isSquare(), "Copy error: the square matrix flag has not been copied properly.");
        unsigned char i;

        for( i = 0; i < 2; i++ )
        {
            QVERIFY2(B.getSize(i) == 0, "Copy error: the size of each matrix dimension must be 0.");
        }
    FAIL_ON_EXCEPTION

    // Test copy of any matrix to an empty matrix
    TRY
        Matrix<double,unsigned char,2> A;
        Matrix(B,double,unsigned char,2) {3,3} End;
        unsigned char i;

        for( i = 0; i < B.getLength(); i++ )
        {
            B(i) = M_PI * ( i + 1 );
        }

        A.copy( B );
        QVERIFY2(A.getLength() == B.getLength(), "Copy error: the lengths of the two matrices must be the same.");
        QVERIFY2(B.isSquare(), "Copy error: the square matrix flag has not been copied properly.");

        for( i = 0; i < 2; i++ )
        {
            QVERIFY2(A.getSize(i) == B.getSize(i), "Copy error: the sizes of the two matrices must be the same.");
        }

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2(A(i) == B(i), "Copy error: each data value of the two matrices must be equal.");
        }
    FAIL_ON_EXCEPTION

    // Test copy of any matrix to any matrix
    TRY
        Matrix(A,double,unsigned char,2) {2,4} End;
        Matrix(B,double,unsigned char,2) {5,5} End;
        unsigned char i;

        for( i = 0; i < B.getLength(); i++ )
        {
            B(i) = M_PI * ( i + 1 );
        }

        A.copy( B );
        QVERIFY2(A.getLength() == B.getLength(), "Copy error: the lengths of the two matrices must be the same.");
        QVERIFY2(B.isSquare(), "Copy error: the square matrix flag has not been copied properly.");

        for( i = 0; i < 2; i++ )
        {
            QVERIFY2(A.getSize(i) == B.getSize(i), "Copy error: the sizes of the two matrices must be the same.");
        }

        for( i = 0; i < A.getLength(); i++ )
        {
            QVERIFY2(A(i) == B(i), "Copy error: each data value of the two matrices must be equal.");
        }
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates two \c Matrix classes and checks if equality check works properly.
*  \version 1.0.0a
*  \date    4 February 2011
*/
void MatrixTest::testIsEqualTo()
{
    // Test equality of identical matrices and then with an element changed
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix<double,unsigned char,2> B( A );
        QVERIFY2( A.isEqualTo( B ), "Comparison error: equality not recognized." );
        B(14) = 0;
        QVERIFY2( !( A.isEqualTo( B ) ), "Comparison error: inequality not recognized." );
    FAIL_ON_EXCEPTION

    // Test equality in matrices of different sizes with the same values
    TRY
        Matrix(A,double,unsigned char,2) {3,5} End;
        Matrix(B,double,unsigned char,2) {5,3} End;

        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
            B(i) = i + 1;
        }

        QVERIFY2( !( A.isEqualTo( B ) ), "Comparison error: inequality not recognized." );
    FAIL_ON_EXCEPTION
}


/**
*  Instantiates a \c Matrix class and checks if its symmetry is properly recognized.
*  \version 1.0.0a
*  \date    1 February 2011
*/
void MatrixTest::testIsSymmetric()
{
    // Test symmetry of a square matrix
    TRY
        Matrix(A,double,unsigned char,2) {3,3} End;
        unsigned char i, j;

        for( i = 0; i < A.getSize(0); i++ )
        {
            for( j = i; j < A.getSize(0); j++ )
            {
                A(i,j) = A.getSize(0) * i + j + 1;
                A(j,i) = A(i,j);
            }
        }

        QVERIFY2( A.isSymmetric(), "isSymmetric error: symmetry not recognized." );
        i = A(1,2);
        A(1,2) = 0;
        QVERIFY2( !A.isSymmetric(), "isSymmetric error: symmetry recognized." );
        A(1,2) = i;
        i = A(0,2);
        A(0,2) = 0;
        QVERIFY2( !A.isSymmetric(), "isSymmetric error: symmetry recognized." );
        A(0,2) = i;
        A(0,1) = 0;
        QVERIFY2( !A.isSymmetric(), "isSymmetric error: symmetry recognized." );
    FAIL_ON_EXCEPTION

#ifdef DEBUG
    // Test matrix not square
    TRY
        Matrix(A,double,unsigned char,2) {3,4} End;
        A.isSymmetric();
    EXPECT_EXCEPTION( "isSymmetric error: matrix not square not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and checks that its Cholesky decomposition is calculated correctly.
*  \version 1.1.0a
*  \date    3 February 2011
*/
void MatrixTest::testCholesky()
{
    // Test Cholesky decomposition of a symmetric positive-definite matrix
    TRY
        Matrix(A,double,unsigned char,2) {3,3} End;
        unsigned char i, j, k = 1;

        for( i = 0; i < A.getSize(0); i++ )
        {
            for( j = i; j < A.getSize(0); j++, k++ )
            {
                A(i,j) = k;
                A(j,i) = A(i,j);
            }
        }

        Matrix<double,unsigned char,2> B( A );
        B *= A.transpose();
        Matrix(C,double,unsigned char,2) {3,3} End;
        C = B.cholesky();
        Matrix(D,double,unsigned char,2) {3,3} End;
        D = C * C.transpose();

        for( i = 0; i < C.getLength(); i++ )
        {
            QVERIFY2( fabs( D(i) - B(i) ) < 1e-14, "Cholesky error: calculation not accurate." );
        }
    FAIL_ON_EXCEPTION

    // Test operation not supported
    TRY
        Matrix(A,double,unsigned char,1) {3} End;
        A.cholesky();
    EXPECT_EXCEPTION( "Cholesky error: operation not supported not recognized." )

#ifdef DEBUG
    // Test Cholesky decomposition of a symmetric but not positive-definite matrix
    TRY
        Matrix(A,double,unsigned char,2) {3,3} End;
        unsigned char i, j;

        for( i = 0; i < A.getSize(0); i++ )
        {
            for( j = i; j < A.getSize(0); j++ )
            {
                A(i,j) = A.getSize(0) * i + j + 1;
                A(j,i) = A(i,j);
            }
        }

        Matrix<double,unsigned char,2> B( A );
        B *= A.transpose();
        Matrix(C,double,unsigned char,2) {3,3} End;
        C = B.cholesky();
    EXPECT_EXCEPTION( "Cholesky error: matrix not positive-definite not recognized." )

    // Test matrix not square
    TRY
        Matrix(A,double,unsigned char,2) {3,4} End;
        A.cholesky();
    EXPECT_EXCEPTION( "Cholesky error: matrix not square not recognized." )

    // Test matrix not symmetric
    TRY
        Matrix(A,double,unsigned char,2) {3,3} End;
        unsigned char i, j, k = 1;

        for( i = 0; i < A.getSize(0); i++ )
        {
            for( j = i; j < A.getSize(0); j++, k++ )
            {
                A(i,j) = k;
                A(j,i) = A(i,j);
            }
        }

        Matrix<double,unsigned char,2> B( A );
        B *= A.transpose();
        B(1) = 0;
        B.cholesky();
    EXPECT_EXCEPTION( "Cholesky error: matrix not symmetric not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and checks that its diagonal elements are extracted correctly.
*  \version 1.0.0a
*  \date    31 January 2011
*/
void MatrixTest::testDiag()
{
    // Test diagonal extraction of a square matrix
    TRY
        Matrix(A,double,unsigned char,2) {4,4} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix(B,double,unsigned char,1) {4} End;
        B = A.diag();
        QVERIFY2( B(0) == 1, "Diag error: extracted value is wrong." );
        QVERIFY2( B(1) == 6, "Diag error: extracted value is wrong." );
        QVERIFY2( B(2) == 11, "Diag error: extracted value is wrong." );
        QVERIFY2( B(3) == 16, "Diag error: extracted value is wrong." );
    FAIL_ON_EXCEPTION

    // Test operation not supported
    TRY
        Matrix(A,double,unsigned char,1) {3} End;
        A.diag();
    EXPECT_EXCEPTION( "Diag error: operation not supported not recognized." )

#ifdef DEBUG
    // Test matrix not square
    TRY
        Matrix(A,double,unsigned char,2) {3,4} End;
        A.diag();
    EXPECT_EXCEPTION( "Diag error: matrix not square not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and checks that its trace is calculated correctly.
*  \version 1.0.0a
*  \date    28 January 2011
*/
void MatrixTest::testTrace()
{
    // Test trace of a square matrix
    TRY
        Matrix(A,double,unsigned char,2) {4,4} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        QVERIFY2( A.trace() == 34, "Trace error: calculation is wrong." );
    FAIL_ON_EXCEPTION

    // Test operation not supported
    TRY
        Matrix(A,double,unsigned char,1) {3} End;
        A.trace();
    EXPECT_EXCEPTION( "Trace error: operation not supported not recognized." )

#ifdef DEBUG
    // Test matrix not square
    TRY
        Matrix(A,double,unsigned char,2) {3,4} End;
        A.trace();
    EXPECT_EXCEPTION( "Trace error: matrix not square not recognized." )
#endif
}


/**
*  Instantiates a \c Matrix class and checks that its transpose is extracted correctly.
*  \version 1.0.0a
*  \date    31 January 2011
*/
void MatrixTest::testTranspose()
{
    // Test transpose extraction of a square matrix
    TRY
        Matrix(A,double,unsigned char,2) {3,4} End;
        unsigned char i;

        for( i = 0; i < A.getLength(); i++ )
        {
            A(i) = i + 1;
        }

        Matrix(B,double,unsigned char,2) {4,3} End;
        B = A.transpose();
        char msg[] = "Transpose error: extracted value is wrong.";
        QVERIFY2( B(0,0) == A(0,0), msg );
        QVERIFY2( B(0,1) == A(1,0), msg );
        QVERIFY2( B(0,2) == A(2,0), msg );
        QVERIFY2( B(1,0) == A(0,1), msg );
        QVERIFY2( B(1,1) == A(1,1), msg );
        QVERIFY2( B(1,2) == A(2,1), msg );
        QVERIFY2( B(2,0) == A(0,2), msg );
        QVERIFY2( B(2,1) == A(1,2), msg );
        QVERIFY2( B(2,2) == A(2,2), msg );
        QVERIFY2( B(3,0) == A(0,3), msg );
        QVERIFY2( B(3,1) == A(1,3), msg );
        QVERIFY2( B(3,2) == A(2,3), msg );
    FAIL_ON_EXCEPTION

    // Test operation not supported
    TRY
        Matrix(A,double,unsigned char,1) {3} End;
        A.transpose();
    EXPECT_EXCEPTION( "Transpose error: operation not supported not recognized." )
}
